Try every configured comment marker when scanning for callouts - #362
Open
youdie006 wants to merge 1 commit into
Open
Try every configured comment marker when scanning for callouts#362youdie006 wants to merge 1 commit into
youdie006 wants to merge 1 commit into
Conversation
The inner loop in EscapeHTMLCallouts searches the configured markers, but breaks out of that search on the first non-match, so only Comments[0] can ever match and later entries are dead. Reordering the same set changes the output: with [// #] a line marked with # renders escaped, and with [# //] a line marked with // does. IsSafeURL and maybeAutoLink both scan their prefix lists to the end; this is the only one that stops at the first miss. The Parse: label and its continue Parse on the success path show the inner loop was meant to be a search.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
RendererOptions.Commentsis documented athtml/renderer.go:112as "a list of comments the renderer should detect", and it is a[][]byte.EscapeHTMLCalloutsloops over that list, butbreaks out of the loop on the first non-match (html/renderer.go:888):The loop is a search over candidate markers, so a non-match should move to the next candidate. Because it breaks instead, only
Comments[0]is ever live and every later entry is dead.The symptom is that reordering the same set changes the output:
Same two markers, same source, different HTML.
Your other prefix-list scanners try every entry
parser/url.go:21--IsSafeURLloopsPathsandcontinues past a non-candidateparser/url.go:38-- the same overURIsparser/inline.go:487--maybeAutoLinkloopsprotocolPrefixes, also[][]byte, also a fixed-offsetHasPrefixtest, and falls through to the next prefixThree sites with the same shape, and the callout loop is the only one that stops at the first miss.
The
Parse:label points the same way: the success path doescontinue Parse, which only earns its keep if the inner loop can reach candidate 2. Today it cannot.Why it went unnoticed
html/callouts_test.go:19setsopts.Comments = [][]byte{[]byte("//")}-- a one-element list, wherebreakandcontinueare indistinguishable. So the existing test could not have caught this.The fix
break->continue, one line. A test covering both orderings of[// #], with a third line using no marker so the escape path stays pinned.Behaviour change
Only for callers configuring two or more markers. With a single marker the two keywords are identical, so nothing changes there. No existing test row has to change -- the suite is green unmodified.
Verification
Exactly what the workflow runs (
go test -v . && ./ast && ./parser && ./html):go vet ./...clean.gofmt -ldoes not list either file I touched (it does list five pre-existing files elsewhere in the tree, which I left alone).I checked the new test pins the iteration rather than the keyword, from three directions:
continueback tobreak<<N>>becomes a calloutc <<9>>rowcontinuebut iterateComments[:1]The third one is the point: it fails for the same reason the original does, which shows the test is about reaching the later entries and not about the
//vs#keywords.What I did not change
EscapeHTMLand theEscapertable, thei+lc < ldbound (correct as-is --IsCalloutneeds at least five bytes),parser.IsCallout, and theComments != nildispatch inCodeBlockathtml/renderer.go:925.Disclosure: AI-assisted. I found and prepared this with an AI assistant, and I ran and verified everything above myself.